package com.piece.core.framework.util.string;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.JSONLibDataFormatSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.*;
import com.piece.core.framework.annotation.translate.JsonMask;
import com.piece.core.framework.exception.ServerException;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.util.collection.MapUtil;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * Json工具类
 */
public class JsonUtil {

    private static final SerializeConfig config;
    private static final ObjectMapper MAPPER = new ObjectMapper();

    static {
        config = new SerializeConfig();
        config.put(java.util.Date.class, new JSONLibDataFormatSerializer()); // 使用和json-lib兼容的日期输出格式
        config.put(java.sql.Date.class, new JSONLibDataFormatSerializer()); // 使用和json-lib兼容的日期输出格式

        // 忽略在json字符串中存在，但是在java对象中不存在对应属性的情况
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 忽略空Bean转json的错误
        MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
        // 允许不带引号的字段名称
        MAPPER.configure(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES.mappedFeature(), true);
        // 允许单引号
        MAPPER.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true);
        // allow int startWith 0
        MAPPER.configure(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature(), true);
        // 允许字符串存在转义字符：\r \n \t
        MAPPER.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
        // 排除空值字段
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 使用驼峰式
        MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CAMEL_CASE);
        // 使用bean名称
        MAPPER.enable(MapperFeature.USE_STD_BEAN_NAMING);
        // 所有日期格式都统一为固定格式
        //MAPPER.setDateFormat(new SimpleDateFormat(DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS));
        //MAPPER.setTimeZone(TimeZone.getTimeZone(DateUtil.TIME_ZONE_GMT8));
    }

    private static final SerializerFeature[] features = {
            SerializerFeature.WriteMapNullValue, // 输出空置字段
            SerializerFeature.WriteNullListAsEmpty, // list字段如果为null，输出为[]，而不是null
            SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null，输出为0，而不是null
            SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null，输出为false，而不是null
            SerializerFeature.WriteNullStringAsEmpty // 字符类型字段如果为null，输出为""，而不是null
    };

    /**
     * Object转json字符串
     */
    public static String toJson(Object object) {
        return JSON.toJSONString(object, config, (ValueFilter) (o, key, value) -> {
            try {
                // 脱敏数据处理
                Field field = o.getClass().getDeclaredField(key);
                JsonMask sensitive = field.getAnnotation(JsonMask.class);
                if (null != sensitive && value instanceof String) {
                    String data = Convert.toString(value);
                    if (StringUtil.isNotBlank(data)) {
                        switch (sensitive.type()) {
                            case PASSWORD:
                                return StringUtil.mask(data);
                            case ID_CARD:
                            case PHONE:
                                return StringUtil.mask(data, 3, 4);
                            case BANK_CARD:
                                return StringUtil.mask(data, 4, 4);
                            default:
                                break;
                        }
                    }
                }
            } catch (NoSuchFieldException e) {
                //找不到的field对功能没有影响,空处理
            }
            return value;
        }, features);
    }

    /**
     * json字符串转Object
     */
    public static Object toBean(String json) {
        return JSON.parse(json);
    }

    /**
     * json字符串转对象
     */
    public static <T> T toBean(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz);
    }

    /**
     * json字符串转Object数组
     */
    public static <T> Object[] toArray(String json) {
        return toArray(json, null);
    }

    /**
     * json字符串转对象数组
     */
    public static <T> Object[] toArray(String text, Class<T> clazz) {
        return JSON.parseArray(text, clazz).toArray();
    }

    /**
     * json字符串转List对象
     */
    public static <T> List<T> toList(String json, Class<T> clazz) {
        return JSON.parseArray(json, clazz);
    }

    /**
     * json字符串转map
     */
    public static <K, V> Map<K, V> toMap(String json) {
        if (StringUtil.isEmpty(json)) {
            return MapUtil.empty();
        }
        Map<K, V> m = (Map<K, V>) JSONObject.parseObject(json);
        return m;
    }

    /**
     * json字符串转map
     */
    public static LinkedMap toLinkedMap(String json) {
        LinkedMap m = JSONObject.parseObject(json, LinkedMap.class);
        return m;
    }

    /**
     * 将map转json字符串
     */
    public static <K, V> String mapToString(Map<K, V> map) {
        String s = JSONObject.toJSONString(map);
        return s;
    }

    /**
     * 字符串转换为JsonNode对象
     */
    public static JsonNode parse(String json) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        try {
            return MAPPER.readTree(json);
        } catch (IOException e) {
            throw new ServerException(e.getMessage());
        }
    }

    public static JsonNode parse(byte[] text) {
        try {
            return MAPPER.readTree(text);
        } catch (IOException e) {
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * json字符串特殊字符处理
     */
    public static String formatString(String s) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                case '\"':
                    sb.append("\\\"");
                    break;
                case '/':
                    sb.append("\\/");
                    break;
                case '\b': // 退格
                    sb.append("\\b");
                    break;
                case '\f': // 走纸换页
                    sb.append("\\f");
                    break;
                case '\n':
                    sb.append("\\n"); // 换行
                    break;
                case '\r': // 回车
                    sb.append("\\r");
                    break;
                case '\t': // 横向跳格
                    sb.append("\\t");
                    break;
                default:
                    sb.append(c);
            }
        }
        return sb.toString();
    }
}
